package dnet

import (
	"bufio"
	"fmt"
	"net"
	"runtime"
	"strconv"
)

type DNetFtpServConnHandler struct {
	owner      *DNetFtpServ
	pwd        string
	conn       net.Conn
	user, pass string
	writer     *bufio.Writer
	reader     *bufio.Reader
}

func NewServConnHandler(owner *DNetFtpServ, conn net.Conn) *DNetFtpServConnHandler {
	rval := &DNetFtpServConnHandler{owner: owner}
	rval.conn = conn
	rval.reader = bufio.NewReader(conn)
	rval.writer = bufio.NewWriter(conn)
	return rval
}

func (this *DNetFtpServConnHandler) writeMessage(code int, msg string) error {
	lines := getMessageLines(msg)

	for idx, line := range lines {
		if idx < len(lines)-1 {
			if _, err := this.writer.WriteString(fmt.Sprintf("%d-%s\r\n", code, line)); err != nil {
				return err
			}
		} else {
			if _, err := this.writer.WriteString(fmt.Sprintf("%d %s\r\n", code, line)); err != nil {
				return err
			}
		}
	}

	return this.writer.Flush()
}

func (this *DNetFtpServConnHandler) clientHandleEntry() {
	this.writeMessage(FTP_STATUS_SERV_READY, "DFtpServ")
	for {
		line, isPrefix, err := this.reader.ReadLine()
		if err != nil {
			break
		}
		if isPrefix {

		}

		this.handleCommand(string(line))
	}
}

func (this *DNetFtpServConnHandler) handleCommandUser(cmd *FtpCmdRequest) {
	this.user = cmd.Param
	this.writeMessage(FTP_STATUS_USER_OK, "ok")
}

func (this *DNetFtpServConnHandler) handleCommandPASS(cmd *FtpCmdRequest) {
	this.pass = cmd.Param
	fn := this.owner.OnAuthEvent
	if fn != nil {
		if !fn(cmd) {
			this.writeMessage(FTP_STATUS_LOGIN_FAIL, "auth err")
			return
		}
	}
	this.writeMessage(FTP_STATUS_LOGIN_OK, fmt.Sprintf("%s logged in", this.user))
}

func (this *DNetFtpServConnHandler) handleCommandSYST(cmd *FtpCmdRequest) {
	this.writeMessage(215, runtime.GOOS)
}

func (this *DNetFtpServConnHandler) handleCommandPWD(cmd *FtpCmdRequest) {
	cmd.Response(FTP_STATUS_PATH_READY, fmt.Sprintf("%s is the current directory", strconv.Quote(this.pwd)))
}

func (this *DNetFtpServConnHandler) handleCommandTYPE(cmd *FtpCmdRequest) {
	cmd.Response(FTP_STATUS_SUCC, "ok")
}

func (this *DNetFtpServConnHandler) handleCommandPASV(cmd *FtpCmdRequest) {
	_, port := SplitIPAndPort(this.owner.listener.addr)
	cmd.Response(FTP_STATUS_PASV, fmt.Sprintf("Entering Passive Mode (127,0,0,1,%d)", port))
}

func (this *DNetFtpServConnHandler) handleCommandCWD(cmd *FtpCmdRequest) {
	cmd.ChangePWD(cmd.Param)
	cmd.Response(FTP_STATUS_PATH_READY, this.pwd)
}

func (this *DNetFtpServConnHandler) handleCommand(cmd string) {
	cmdR := NewFtpCmdRequest(this, cmd)
	if this.owner.OnExecCMDEvent != nil {
		if !this.owner.OnExecCMDEvent(cmdR) {
			return
		}
	}

	command := cmdR.Command
	if command == FTP_CMD_USER {
		this.handleCommandUser(cmdR)
	} else if command == FTP_CMD_PASS {
		this.handleCommandPASS(cmdR)
	} else if command == FTP_CMD_SYST {
		this.handleCommandSYST(cmdR)
	} else if command == FTP_CMD_TYPE {
		this.handleCommandTYPE(cmdR)
	} else if command == FTP_CMD_PASV {
		this.handleCommandPASV(cmdR)
	} else if command == FTP_CMD_CWD {
		this.handleCommandCWD(cmdR)
	} else {
		if command == FTP_CMD_AUTH {
			if cmdR.Param == "TLS" {
				this.writeMessage(FTP_STATUS_FILE_INVALID, "TLS invalid!")
				return
			} else if cmdR.Param == "SSL" {
				this.writeMessage(FTP_STATUS_FILE_INVALID, "SSL invalid!")
				return
			}
		}
		this.writeMessage(FTP_STATUS_CMD_INVALID, fmt.Sprintf("unkown cmd:%s, param:%s", command, cmdR.Param))
		fmt.Printf("未处理的命令[%s] [%s]\r\n", command, cmdR.Param)
	}
}
